/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.client.datatree;

import net.bioteam.appweb.gwt.apps.client.StaticHolder;
import net.bioteam.appweb.gwt.apps.client.Util.ApplicationCallBack;
import net.bioteam.appweb.gwt.apps.client.Util.GwtRpcDataSource;
import net.bioteam.appweb.gwt.apps.client.Util.Util;
import net.bioteam.appweb.gwt.apps.clientandserver.Constant;
import net.bioteam.appweb.gwt.apps.clientandserver.datatree.FileNode;
import net.bioteam.appweb.gwt.apps.clientandserver.datatree.FileNodes;
import net.bioteam.appweb.gwt.apps.clientandserver.datatree.FileNodesAsync;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.fields.DataSourceBooleanField;
import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.util.JSOHelper;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;

public class DataTreeDataSource extends GwtRpcDataSource
{

	/**
	 * Server never uses and changes fileID, so we just generate a arbitrary ID
	 */
	private int fileID = 100;

	private int getFileID()
	{
		return fileID++;
	}

	public TreeGrid treeGrid;

	public DataTreeDataSource()
	{

		super();

		DataSourceIntegerField idField = new DataSourceIntegerField("id");
		idField.setPrimaryKey(true);

		DataSourceIntegerField sizeField = new DataSourceIntegerField("size");

		DataSourceTextField nameField = new DataSourceTextField("name");
		DataSourceTextField snameField = new DataSourceTextField("servername");
		DataSourceBooleanField folderField = new DataSourceBooleanField("folder");

		DataSourceTextField href = new DataSourceTextField("href");
		setFields(idField, nameField, snameField, folderField, href, sizeField);

	}

	public void copyValues(FileNode from, TreeNode record, boolean withID)
	{
		record.setAttribute("name", from.name);
		record.setAttribute("servername", from.name);
		record.setAttribute("folder", !from.leaf);
		if (from.leaf)
			record.setAttribute("size", from.size);
		if (from.href != null)
			record.setAttribute("href", from.href);
		if (withID)
		{
			record.setAttribute("id", getFileID());
		}
	}
	
	

	@Override
	protected void executeAdd(final String requestId, final DSRequest request, final DSResponse response)
	{
		Util.debugJSObject(request.getJsObj(), "request");
		Util.debugJSObject(request.getData(), "data");
		Util.debugJSObject(request.getAttributeAsJavaScriptObject("originalData"), "originalData");
		
		JavaScriptObject obj = request.getData();
		final TreeNode node = new TreeNode(obj);
		//TreeGrid treeGrid = (TreeGrid) Canvas.getById(request.getComponentId());
		TreeNode parent = treeGrid.getTree().findById(node.getAttributeAsString("parentId"));
		final String parentPath = treeGrid.getTree().getPath(parent);
		
		ApplicationCallBack<FileNode> callback = new ApplicationCallBack<FileNode>()
		{

			public void onFailureAfter(Throwable caught)
			{

				response.setStatus(RPCResponse.STATUS_FAILURE);
				processResponse(requestId, response);
				SC.warn(caught.getMessage(), StaticHolder.dumpB);
			}

			public void onSuccessAfter(FileNode result)
			{
				ListGridRecord[] list = new ListGridRecord[1];
				TreeNode returnNode=new TreeNode();
				copyValues(result, returnNode, true);
				// We do not receive removed record from server.
				// Return record from request.
				list[0] = returnNode;
				returnNode.setParentID(node.getAttributeAsString("parentId"));
				response.setData(list);
				processResponse(requestId, response);

			}

			public void execute()
			{
				FileNodesAsync fileNodesProxy = GWT.create(FileNodes.class);
				if (node.getAttribute("_appoldname")!=null)
				{
					//copy menu
					String oldPath=myTranslatePath(parentPath+"/"+node.getAttributeAsString("_appoldname"));
					String newPath=myTranslatePath(parentPath+"/"+node.getAttributeAsString("name"));
					fileNodesProxy.copyFile(oldPath, newPath, this);
				} else if (node.getAttribute("_appnewdir")!=null)
				{
					//new dir
					String newPath=myTranslatePath(parentPath+"/"+node.getAttributeAsString("name"));
					fileNodesProxy.makeDir(newPath, this);
				} else if (node.getAttribute("_myjobpath")!=null)
				{
					//drag and drop from jobFiles
					String jobPath=node.getAttribute("_myjobpath");
					int index=jobPath.lastIndexOf('/');
					String name=jobPath.substring(index);
					String oldPath=myTranslatePath(jobPath);
					String newPath=myTranslatePath(parentPath+name);
					fileNodesProxy.copyFile(oldPath, newPath, this);
				}
			}

		};
		callback.execute();

	}

	public String myTranslatePath(String path)
	{
		return translatePath(path);
	}

	
	public  static String translatePath(String path)
	{
		if (path.startsWith("/" + Constant.server_file_public_name))
		{
			return path;
		} else if (path.startsWith("/" + Constant.data_name) || path.startsWith("/" + Constant.job_name))
		{
			return "/" + Constant.server_file_user_name + path;
		} else
		{
			return path;
		}
	}



	@Override
	protected void executeFetch(final String requestId, final DSRequest request, final DSResponse response)
	{

		JavaScriptObject obj = request.getAttributeAsJavaScriptObject("parentNode");
		final TreeNode parentNode = new TreeNode(obj);
		//TreeGrid treeGrid = (TreeGrid) Canvas.getById(request.getComponentId());
		final String serverPath = myTranslatePath(treeGrid.getTree().getPath(parentNode));

		ApplicationCallBack<FileNode[]> callback = new ApplicationCallBack<FileNode[]>()
		{

			public void onFailureAfter(Throwable caught)
			{
				response.setStatus(RPCResponse.STATUS_FAILURE);
				processResponse(requestId, response);
				SC.warn(caught.getMessage(), StaticHolder.dumpB);

			}

			public void onSuccessAfter(FileNode[] result)
			{
				ListGridRecord[] list = new ListGridRecord[result.length];
				for (int i = 0; i < list.length; i++)
				{
					TreeNode record = new TreeNode();
					FileNode node = result[i];
					copyValues(node, record, true);
					record.setParentID(parentNode.getAttributeAsString("id"));
					list[i] = record;
				}
				response.setData(list);
				processResponse(requestId, response);
			}

			public void execute()
			{
				FileNodesAsync fileNodesProxy = GWT.create(FileNodes.class);
				fileNodesProxy.getChildren(serverPath, this);
			}

		};
		callback.execute();

	}

	@Override
	protected void executeRemove(final String requestId, final DSRequest request, final DSResponse response)
	{
		JavaScriptObject obj = request.getData();
		final TreeNode node = new TreeNode(obj);
		//TreeGrid treeGrid = (TreeGrid) Canvas.getById(request.getComponentId());
		final String serverPath = myTranslatePath(treeGrid.getTree().getPath(node));
		ApplicationCallBack<String> callback = new ApplicationCallBack<String>()
		{

			public void onFailureAfter(Throwable caught)
			{

				response.setStatus(RPCResponse.STATUS_FAILURE);
				processResponse(requestId, response);
				SC.warn(caught.getMessage(), StaticHolder.dumpB);
			}

			public void onSuccessAfter(String result)
			{
				ListGridRecord[] list = new ListGridRecord[1];
				// We do not receive removed record from server.
				// Return record from request.
				list[0] = node;
				response.setData(list);
				processResponse(requestId, response);

			}

			public void execute()
			{
				FileNodesAsync fileNodesProxy = GWT.create(FileNodes.class);
				fileNodesProxy.deleteFile(serverPath, this);
			}

		};
		callback.execute();
	}


	@Override
	protected void executeUpdate(final String requestId, final DSRequest request, final DSResponse response)
	{
		Util.debugJSObject(request.getJsObj(), "request");
		Util.debugJSObject(request.getData(), "data");
		Util.debugJSObject(request.getAttributeAsJavaScriptObject("originalData"), "originalData");
		Util.debugJSObject(request.getAttributeAsJavaScriptObject("oldValues"), "oldValues");
		
		
		final TreeNode oldNode= new TreeNode(request.getAttributeAsJavaScriptObject("oldValues"));
		JavaScriptObject newData = request.getData();
		final TreeNode newNode = new TreeNode(newData);

		//this is old parent.
		//TreeGrid treeGrid = (TreeGrid) Canvas.getById(request.getComponentId());
		TreeNode parent = treeGrid.getTree().findById(oldNode.getAttributeAsString("parentId"));
		String parentPath = treeGrid.getTree().getPath(parent);
		
		final String oldPath = myTranslatePath(parentPath + "/" + oldNode.getAttribute("name"));
		final String newPath = myTranslatePath(parentPath + "/" + newNode.getAttribute("name"));

		ApplicationCallBack<FileNode> callback = new ApplicationCallBack<FileNode>()
		{
			public void onFailureAfter(Throwable caught)
			{
				response.setStatus(RPCResponse.STATUS_FAILURE);
				processResponse(requestId, response);
				SC.warn(caught.getMessage(), StaticHolder.dumpB);
			}

			public void onSuccessAfter(FileNode result)
			{
				ListGridRecord[] list = new ListGridRecord[1];
				
				//copy properties updated from server to client node.
				TreeNode returnNode=new TreeNode();
				copyValues(result, returnNode, false);
				if (newNode.getAttribute("parentId")!=null)
				{
					//updating
					JSOHelper.apply(returnNode.getJsObj(), newNode.getJsObj());
					list[0] = newNode;
				} else
				{
					//renaming
					JSOHelper.apply(returnNode.getJsObj(), oldNode.getJsObj());
					list[0] = oldNode;
				}
				response.setData(list);
				processResponse(requestId, response);
			}

			public void execute()
			{
				FileNodesAsync fileNodesProxy = GWT.create(FileNodes.class);
				if (newNode.getAttribute("parentId")!=null)
				{
					//this is a drag and drop operation
					//TreeGrid treeGrid = (TreeGrid) Canvas.getById(request.getComponentId());
					TreeNode newParent = treeGrid.getTree().findById(newNode.getAttributeAsString("parentId"));
					String newParentPath = treeGrid.getTree().getPath(newParent);
					String movedPath= myTranslatePath(newParentPath + "/" + newNode.getAttribute("name"));
					fileNodesProxy.moveFile(oldPath, movedPath, this);
					
				} else
				{
					//this is a rename operation.
					fileNodesProxy.renameFile(oldPath, newPath, this);
				}
			}

		};
		callback.execute();

	}
	
	
	
}
